﻿using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Windows.Forms;
using DataAccessLayer;
using Editor.Properties;

namespace Editor
{
    public partial class MainForm : Form, IEditorView
    {
        #region Objects
        private Rectangle viewport;

        private readonly Size viewportSize;

        private Image curImage;

        private readonly Size screenDiff;

        private Rectangle curSourceRect;

        private Rectangle curColRect;

        private string curFilename;

        private bool bIgnoreEvent;

        private readonly IPresenterFacade presenter;

        private ListView curLv;

        private int curColRectIndex;

        private readonly Pen bluePen;

        private readonly Pen redPen;

        private bool bDrawProtImg;

        private bool bDrawEnemyImg;

        private bool bDrawMinibossImg;

        private bool bDrawBossImg;

        private bool bDrawFighterPodImg;

        private bool bDrawbDrawBulletImg;

        private bool bDrawWeaponImg;

        private bool bDrawEffectImg;

        private bool bCanProtDrawRect;

        private bool bCanEnemyDrawRect;

        private bool bCanMinibossDrawRect;

        private bool bCanBossDrawRect;

        private bool bCanFighterPodDrawRect;

        private bool bCanBulletDrawRect;

        private bool bCanWeaponDrawRect;

        private bool bCanEffectDrawRect;
        #endregion


        #region Ctor
        public MainForm()
        {
            InitializeComponent();

            presenter = new PresenterFacade();

            EditorStartData startData = presenter.LoadApplicationData(Settings.Default.LastSaveFile);

            LoadGameData(startData);

            InitStartData(startData);

            viewportSize = new Size(600, 800);

            screenDiff = new Size(menuContainer.Panel1.Width - viewportSize.Width,
                menuContainer.Panel1.Height - viewportSize.Height);

            int top = (int)(screenDiff.Height * 0.5f);
            int left = (int)(screenDiff.Width * 0.5f);

            viewport = new Rectangle(left, top, viewportSize.Width, viewportSize.Height);

            objectsCanvas.Invalidate();

            curColRectIndex = -1;

            bluePen = new Pen(Color.Blue);

            redPen = new Pen(Color.Red);
        }
        #endregion


        #region Protagonist
        private void protagonistsLv_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (protagonistsLv.SelectedIndices.Count == 0) return;

            bDrawProtImg = true;
            bCanProtDrawRect = false;

            int id = int.Parse(protagonistsLv.SelectedItems[0].SubItems[0].Text);

            Protagonist prot = presenter.ProtagonistPresenter.GetProtagonist(id);

            bIgnoreEvent = true;

            protHpNud.Value = prot.Hp;
            protPowerNud.Value = prot.Power;
            protSpeedNud.Value = prot.Speed;
            protWeaponSlotsNud.Value = prot.WeaponSlots;

            protPosXNud.Value = (decimal)prot.Position.X;
            protPosYNud.Value = (decimal)prot.Position.Y;

            protSrXNud.Value = prot.SourceRect.X;
            protSrYNud.Value = prot.SourceRect.Y;
            protSrWidthNud.Value = prot.SourceRect.Width;
            protSrHeightNud.Value = prot.SourceRect.Height;

            if (prot is NormalProtagonist)
            {
                NormalProtagonist nProt = (NormalProtagonist)prot;
                protColRectsLv.Items.Clear();
                protColRectsLv.Items.Add(new ListViewItem(new[]
                                                              {
                                                                  nProt.CollisionRectangle.X.ToString(),
                                                                  nProt.CollisionRectangle.Y.ToString(),
                                                                  nProt.CollisionRectangle.Width.ToString(),
                                                                  nProt.CollisionRectangle.Height.ToString()
                                                              }));
            }
            else if (prot is ProtagonistEx)
            {
                ProtagonistEx protEx = (ProtagonistEx)prot;
                protColRectsLv.Items.Clear();
                foreach (var colr in protEx.CollisionRectangles)
                {
                    protColRectsLv.Items.Add(new ListViewItem(new[]
                                                              {
                                                                  colr.X.ToString(),
                                                                  colr.Y.ToString(),
                                                                  colr.Width.ToString(),
                                                                  colr.Height.ToString()
                                                              }));
                }
            }

            bIgnoreEvent = false;

            protCanvasPnl.Invalidate();
        }

        private void protSpritesLbx_SelectedIndexChanged(object sender, EventArgs e)
        {
            bDrawProtImg = false;
            protCanvasPnl.Invalidate();
        }

        private void protCanvasPnl_Paint(object sender, PaintEventArgs e)
        {
            int selectedProtIndex = protagonistsLv.SelectedIndices.Count > 0 ? protagonistsLv.SelectedIndices[0] : - 1;
            int protId = -1;
            Protagonist prot = null;
            if(selectedProtIndex > -1)
            {
                protId = int.Parse(protagonistsLv.SelectedItems[0].SubItems[0].Text);
                prot = presenter.ProtagonistPresenter.GetProtagonist(protId);
            }

            // draw image
            if (bDrawProtImg)
            {
                if (prot == null || string.IsNullOrEmpty(prot.TextureName))
                    return;
               
                e.Graphics.DrawImage(Image.FromFile(prot.TextureName), Point.Empty);
            }
            else
            {
                if(protSpritesLbx.SelectedIndex >= 0)
                    e.Graphics.DrawImage(Image.FromFile(protSpritesLbx.Items[protSpritesLbx.SelectedIndex].ToString()), Point.Empty);
            }

            // draw rectangles
            if (!bCanProtDrawRect)
            {
                if (protId > 0)
                {
                    if (prot != null)
                        curSourceRect = prot.SourceRect;

                    if (prot is NormalProtagonist)
                    {
                        e.Graphics.DrawRectangle(redPen, (prot as NormalProtagonist).CollisionRectangle);
                    }
                    else if (prot is ProtagonistEx)
                    {
                        ProtagonistEx protEx = prot as ProtagonistEx;
                        e.Graphics.DrawRectangles(redPen, (from r in protEx.CollisionRectangles
                                                           select new Rectangle(r.X, r.Y, r.Width, r.Height)).ToArray());
                    }
                }
            }
            else
            {
                e.Graphics.DrawRectangle(redPen, curColRect);
            }

            e.Graphics.DrawRectangle(bluePen, curSourceRect);
        }

        private void protHpNud_ValueChanged(object sender, EventArgs e)
        {
            if (protagonistsLv.SelectedIndices.Count == 0 || bIgnoreEvent) return;

            int id = int.Parse(protagonistsLv.SelectedItems[0].SubItems[0].Text);

            presenter.ProtagonistPresenter.SaveData(id, (int)protHpNud.Value, (int)protPowerNud.Value,
                 (int) protSpeedNud.Value,  (int) protWeaponSlotsNud.Value);

            protagonistsLv.SelectedItems[0].SubItems[1].Text = protHpNud.Value.ToString();
        }

        private void protPowerNud_ValueChanged(object sender, EventArgs e)
        {
            if (protagonistsLv.SelectedIndices.Count == 0 || bIgnoreEvent) return;

            int id = int.Parse(protagonistsLv.SelectedItems[0].SubItems[0].Text);

            presenter.ProtagonistPresenter.SaveData(id, (int)protHpNud.Value, (int)protPowerNud.Value,
                 (int)protSpeedNud.Value, (int)protWeaponSlotsNud.Value);

            protagonistsLv.SelectedItems[0].SubItems[2].Text = protPowerNud.Value.ToString();
        }

        private void protSpeedNud_ValueChanged(object sender, EventArgs e)
        {
            if (protagonistsLv.SelectedIndices.Count == 0 || bIgnoreEvent) return;

            int id = int.Parse(protagonistsLv.SelectedItems[0].SubItems[0].Text);

            presenter.ProtagonistPresenter.SaveData(id, (int)protHpNud.Value, (int)protPowerNud.Value,
                 (int)protSpeedNud.Value, (int)protWeaponSlotsNud.Value);

            protagonistsLv.SelectedItems[0].SubItems[3].Text = protSpeedNud.Value.ToString();
        }

        private void protWeaponSlotsNud_ValueChanged(object sender, EventArgs e)
        {
            if (protagonistsLv.SelectedIndices.Count == 0 || bIgnoreEvent) return;

            int id = int.Parse(protagonistsLv.SelectedItems[0].SubItems[0].Text);

            presenter.ProtagonistPresenter.SaveData(id, (int)protHpNud.Value, (int)protPowerNud.Value,
                 (int)protSpeedNud.Value, (int)protWeaponSlotsNud.Value);

            protagonistsLv.SelectedItems[0].SubItems[4].Text = protWeaponSlotsNud.Value.ToString();
        }

        private void protPosXNud_ValueChanged(object sender, EventArgs e)
        {
            if (protagonistsLv.SelectedIndices.Count == 0 || bIgnoreEvent) return;

            int id = int.Parse(protagonistsLv.SelectedItems[0].SubItems[0].Text);

            presenter.ProtagonistPresenter.SetProtagonistPosition(id, (int)protPosXNud.Value, (int)protPosYNud.Value);
        }

        private void protPosYNud_ValueChanged(object sender, EventArgs e)
        {
            if (protagonistsLv.SelectedIndices.Count == 0 || bIgnoreEvent) return;

            int id = int.Parse(protagonistsLv.SelectedItems[0].SubItems[0].Text);

            presenter.ProtagonistPresenter.SetProtagonistPosition(id, (int)protPosXNud.Value, (int)protPosYNud.Value);
        }

        private void protSrXNud_ValueChanged(object sender, EventArgs e)
        {
            if (protagonistsLv.SelectedIndices.Count == 0 || bIgnoreEvent) return;

            int id = int.Parse(protagonistsLv.SelectedItems[0].SubItems[0].Text);

            presenter.ProtagonistPresenter.SetProtagonistSourceRect(id, (int)protSrXNud.Value, (int)protSrYNud.Value,
                 (int)protSrWidthNud.Value, (int)protSrHeightNud.Value);

            protCanvasPnl.Invalidate();
        }

        private void protSrYNud_ValueChanged(object sender, EventArgs e)
        {
            if (protagonistsLv.SelectedIndices.Count == 0 || bIgnoreEvent) return;

            int id = int.Parse(protagonistsLv.SelectedItems[0].SubItems[0].Text);

            presenter.ProtagonistPresenter.SetProtagonistSourceRect(id, (int)protSrXNud.Value, (int)protSrYNud.Value,
                 (int)protSrWidthNud.Value, (int)protSrHeightNud.Value);

            protCanvasPnl.Invalidate();
        }

        private void protSrWidthNud_ValueChanged(object sender, EventArgs e)
        {
            if (protagonistsLv.SelectedIndices.Count == 0 || bIgnoreEvent) return;

            int id = int.Parse(protagonistsLv.SelectedItems[0].SubItems[0].Text);

            presenter.ProtagonistPresenter.SetProtagonistSourceRect(id, (int)protSrXNud.Value, (int)protSrYNud.Value,
                 (int)protSrWidthNud.Value, (int)protSrHeightNud.Value);

            protCanvasPnl.Invalidate();
        }

        private void protSrHeightNud_ValueChanged(object sender, EventArgs e)
        {
            if (protagonistsLv.SelectedIndices.Count == 0 || bIgnoreEvent) return;

            int id = int.Parse(protagonistsLv.SelectedItems[0].SubItems[0].Text);

            presenter.ProtagonistPresenter.SetProtagonistSourceRect(id, (int)protSrXNud.Value, (int)protSrYNud.Value,
                 (int)protSrWidthNud.Value, (int)protSrHeightNud.Value);

            protCanvasPnl.Invalidate();
        }

        private void protWeaponLv_MouseDoubleClick(object sender, MouseEventArgs e)
        {
            if (protagonistsLv.SelectedIndices.Count == 0) return;

            int protId = int.Parse(protagonistsLv.SelectedItems[0].SubItems[0].Text);

            int weaponId = int.Parse(protWeaponLv.SelectedItems[0].SubItems[0].Text);

            string errMsg;
            if(!presenter.ProtagonistPresenter.AddWeaponToProtagonist(protId, weaponId, out errMsg))
            {
                MessageBox.Show(errMsg, Resources.GameEditorTitle);
            }
        }

        private void removeProtColRectBtn_Click(object sender, EventArgs e)
        {
            if(protColRectsLv.SelectedIndices.Count == 0 ||
                protagonistsLv.SelectedIndices.Count == 0)
            {
                return;
            }

            int id = int.Parse(protagonistsLv.SelectedItems[0].SubItems[0].Text);

            presenter.ProtagonistPresenter.RemoveProtagonistCollisionRectangle(id, protColRectsLv.SelectedIndices[0]);

            protColRectsLv.Items.RemoveAt(protColRectsLv.SelectedIndices[0]);

            bIgnoreEvent = true;
            protColRectXNud.Value = 0;
            protColRectYNud.Value = 0;
            protColRectWidthNud.Value = 0;
            protColRectHeightNud.Value = 0;
            bIgnoreEvent = false;
        }

        private void addProtSrcRectOpt_Click(object sender, EventArgs e)
        {
            if(protagonistsLv.SelectedIndices.Count == 0)
            {
                MessageBox.Show(@"Select a protagonist first!", Resources.GameEditorTitle);
                return;
            }

            addProtSrcRectOpt.Checked = !addProtSrcRectOpt.Checked;

            addProtSrcRectOpt.BackColor = addProtSrcRectOpt.Checked
                                                ? Color.LightBlue : SystemColors.Control;

            addProtColRectOpt.Checked = false;

            addProtColRectOpt.BackColor = SystemColors.Control;
        }

        private void addProtColRectOpt_Click(object sender, EventArgs e)
        {
            if (protagonistsLv.SelectedIndices.Count == 0)
            {
                MessageBox.Show(@"Select a protagonist first!", Resources.GameEditorTitle);
                return;
            }

            addProtColRectOpt.Checked = !addProtColRectOpt.Checked;

            addProtColRectOpt.BackColor = addProtColRectOpt.Checked
                                                ? Color.LightBlue : SystemColors.Control;

            addProtSrcRectOpt.Checked = false;

            addProtSrcRectOpt.BackColor = SystemColors.Control;
        }

        private void protCanvasPnl_MouseDown(object sender, MouseEventArgs e)
        {
            bCanProtDrawRect = true;

            Point mousePos = protCanvasPnl.PointToClient(Cursor.Position);

            if (addProtSrcRectOpt.Checked)
                curSourceRect.Location = mousePos;
            else if (addProtColRectOpt.Checked)
                curColRect.Location = mousePos;
        }

        private void protCanvasPnl_MouseMove(object sender, MouseEventArgs e)
        {
            if (!bCanProtDrawRect || e.Button != MouseButtons.Left) return;

            Point mousePos = protCanvasPnl.PointToClient(Cursor.Position);

            if (addProtSrcRectOpt.Checked)
            {
                curSourceRect.Width = mousePos.X - curSourceRect.X;
                curSourceRect.Height = mousePos.Y - curSourceRect.Y;
            }
            else if (addProtColRectOpt.Checked)
            {
                curColRect.Width = mousePos.X - curColRect.X;
                curColRect.Height = mousePos.Y - curColRect.Y;
            }

            protCanvasPnl.Invalidate();
        }

        private void protCanvasPnl_MouseUp(object sender, MouseEventArgs e)
        {
            bCanProtDrawRect = false;

            if (protagonistsLv.SelectedIndices.Count == 0) return;

            int id = int.Parse(protagonistsLv.SelectedItems[0].SubItems[0].Text);

            presenter.ProtagonistPresenter.SetProtagonistSourceRectangle(id, curSourceRect);

            if(!curColRect.IsEmpty)
            {
                presenter.ProtagonistPresenter.SetCollisionRectangle(id, curColRect);

                curColRect = Rectangle.Empty;
            }
        }

        private void addProtOpt_Click(object sender, EventArgs e)
        {
            Protagonist prot = presenter.ProtagonistPresenter.AddProtagonist();

            protagonistsLv.Items.Add(new ListViewItem(new[]
                                                          {
                                                              prot.ID.ToString(),
                                                              prot.Hp.ToString(),
                                                              prot.Power.ToString(),
                                                              prot.Speed.ToString(),
                                                              prot.WeaponSlots.ToString(),
                                                          }));
        }

        private void saveProtEditOpt_Click(object sender, EventArgs e)
        {
            if (protagonistsLv.SelectedIndices.Count == 0) return;

            int id = int.Parse(protagonistsLv.SelectedItems[0].SubItems[0].Text);

            presenter.ProtagonistPresenter.SaveData(id,
                                                    
                                                    new AircraftStats
                                                        {
                                                            Hp = (int)protHpNud.Value,
                                                            Power = (int)protPowerNud.Value,
                                                            Speed = (int)protSpeedNud.Value,
                                                            WeaponSlots = (int)protWeaponSlotsNud.Value
                                                        },
                                                    
                                                    new RectangleProperties
                                                        {
                                                            SourceRectangle = new EditorRect
                                                                                  {
                                                                                      X = (int)protSrXNud.Value,
                                                                                      Y = (int)protSrYNud.Value,
                                                                                      Width = (int)protSrWidthNud.Value,
                                                                                      Height = (int)protSrHeightNud.Value
                                                                                  },
                                                            CollisionRectangles = (from ListViewItem item in protColRectsLv.Items
                                                                                   select new EditorRect
                                                                                              {
                                                                                                  X = int.Parse(item.SubItems[0].Text),
                                                                                                  Y = int.Parse(item.SubItems[1].Text),
                                                                                                  Width = int.Parse(item.SubItems[2].Text),
                                                                                                  Height = int.Parse(item.SubItems[3].Text) 
                                                                                              }).ToList()
                                                        }, 
                                                        
                                                   new EditorVector2
                                                       {
                                                           X = (int)protPosXNud.Value,
                                                           Y = (int)protPosYNud.Value
                                                       });
        }

        private void deleteProtOpt_Click(object sender, EventArgs e)
        {
            if (protagonistsLv.SelectedIndices.Count == 0) return;

            int id = int.Parse(protagonistsLv.SelectedItems[0].SubItems[0].Text);

            presenter.ProtagonistPresenter.DeleteProtagonist(id);

            protagonistsLv.Items.RemoveAt(protagonistsLv.SelectedIndices[0]);

            bIgnoreEvent = true;
            
            protHpNud.Value = 0;
            protPowerNud.Value = 0;
            protSpeedNud.Value = 0;
            protWeaponSlotsNud.Value = 0;
            protPosXNud.Value = 0;
            protPosYNud.Value = 0;
            protHpNud.Value = 0;

            protSrXNud.Value = 0;
            protSrYNud.Value = 0;
            protSrWidthNud.Value = 0;
            protSrHeightNud.Value = 0;

            protColRectsLv.Items.Clear();

            protWeaponLv.SelectedIndices.Clear();

            bIgnoreEvent = false;
        }

        private void setProtSpriteMenuItem_Click(object sender, EventArgs e)
        {
            if (protagonistsLv.SelectedIndices.Count == 0 ||
                protSpritesLbx.SelectedIndex < 0) return;

            int id = int.Parse(protagonistsLv.SelectedItems[0].SubItems[0].Text);

            presenter.ProtagonistPresenter.SetProtagonistSprite(id, protSpritesLbx.SelectedItem.ToString());
        }

        private void protColRectsLv_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (protColRectsLv.SelectedIndices.Count == 0) return;

            bIgnoreEvent = true;

            ListViewItem.ListViewSubItemCollection items = protColRectsLv.SelectedItems[0].SubItems;

            protColRectXNud.Value = decimal.Parse(items[0].Text);
            protColRectYNud.Value = decimal.Parse(items[1].Text);
            protColRectWidthNud.Value = decimal.Parse(items[2].Text);
            protColRectHeightNud.Value = decimal.Parse(items[3].Text);

            bIgnoreEvent = false;
        }

        private void protColRectXNud_ValueChanged(object sender, EventArgs e)
        {
            if (protagonistsLv.SelectedIndices.Count == 0 ||
                protColRectsLv.SelectedIndices.Count == 0 || 
                bIgnoreEvent) return;

            int id = int.Parse(protagonistsLv.SelectedItems[0].SubItems[0].Text);
            int colRectIndex = protColRectsLv.SelectedIndices[0];

            presenter.ProtagonistPresenter.SetCollisionRectangle(id, 
                                                                 colRectIndex,
                                                                 new EditorRect
                                                                    {
                                                                        X = (int)protColRectXNud.Value,
                                                                        Y = (int)protColRectYNud.Value,
                                                                        Width = (int)protColRectWidthNud.Value,
                                                                        Height = (int)protColRectHeightNud.Value
                                                                    });

            protColRectsLv.SelectedItems[0].SubItems[0].Text = protColRectXNud.Value.ToString();

            protCanvasPnl.Invalidate();
        }

        private void protColRectYNud_ValueChanged(object sender, EventArgs e)
        {
            if (protagonistsLv.SelectedIndices.Count == 0 ||
                protColRectsLv.SelectedIndices.Count == 0 ||
                bIgnoreEvent) return;

            int id = int.Parse(protagonistsLv.SelectedItems[0].SubItems[0].Text);
            int colRectIndex = protColRectsLv.SelectedIndices[0];

            presenter.ProtagonistPresenter.SetCollisionRectangle(id,
                                                                 colRectIndex,
                                                                 new EditorRect
                                                                 {
                                                                     X = (int)protColRectXNud.Value,
                                                                     Y = (int)protColRectYNud.Value,
                                                                     Width = (int)protColRectWidthNud.Value,
                                                                     Height = (int)protColRectHeightNud.Value
                                                                 });

            protColRectsLv.SelectedItems[0].SubItems[1].Text = protColRectYNud.Value.ToString();

            protCanvasPnl.Invalidate();
        }

        private void protColRectWidthNud_ValueChanged(object sender, EventArgs e)
        {
            if (protagonistsLv.SelectedIndices.Count == 0 ||
                protColRectsLv.SelectedIndices.Count == 0 ||
                bIgnoreEvent) return;

            int id = int.Parse(protagonistsLv.SelectedItems[0].SubItems[0].Text);
            int colRectIndex = protColRectsLv.SelectedIndices[0];

            presenter.ProtagonistPresenter.SetCollisionRectangle(id,
                                                                 colRectIndex,
                                                                 new EditorRect
                                                                 {
                                                                     X = (int)protColRectXNud.Value,
                                                                     Y = (int)protColRectYNud.Value,
                                                                     Width = (int)protColRectWidthNud.Value,
                                                                     Height = (int)protColRectHeightNud.Value
                                                                 });

            protColRectsLv.SelectedItems[0].SubItems[2].Text = protColRectWidthNud.Value.ToString();

            protCanvasPnl.Invalidate();
        }

        private void protColRectHeightNud_ValueChanged(object sender, EventArgs e)
        {
            if (protagonistsLv.SelectedIndices.Count == 0 ||
                protColRectsLv.SelectedIndices.Count == 0 ||
                bIgnoreEvent) return;

            int id = int.Parse(protagonistsLv.SelectedItems[0].SubItems[0].Text);
            int colRectIndex = protColRectsLv.SelectedIndices[0];

            presenter.ProtagonistPresenter.SetCollisionRectangle(id,
                                                                 colRectIndex,
                                                                 new EditorRect
                                                                 {
                                                                     X = (int)protColRectXNud.Value,
                                                                     Y = (int)protColRectYNud.Value,
                                                                     Width = (int)protColRectWidthNud.Value,
                                                                     Height = (int)protColRectHeightNud.Value
                                                                 });

            protColRectsLv.SelectedItems[0].SubItems[3].Text = protColRectHeightNud.Value.ToString();

            protCanvasPnl.Invalidate();
        }
        #endregion


        #region Enemies
        private void addEnemyOpt_Click(object sender, EventArgs e)
        {
            Enemy enemy = presenter.EnemyPresenter.AddEnemy();

            enemiesLv.Items.Add(new ListViewItem(new[]
                                                          {
                                                              enemy.ID.ToString(),
                                                              enemy.Hp.ToString(),
                                                              enemy.Power.ToString(),
                                                              enemy.Speed.ToString(),
                                                              enemy.WeaponSlots.ToString(),
                                                          }));
        }

        private void saveEnemyInfoOpt_Click(object sender, EventArgs e)
        {
            if (enemiesLv.SelectedIndices.Count == 0) return;

            int id = int.Parse(enemiesLv.SelectedItems[0].SubItems[0].Text);

            var colR = enemiesColRectsLv.Items[0];

            presenter.EnemyPresenter.SaveData(id,

                                                    new AircraftStats
                                                    {
                                                        Hp = (int)enemiesHpNud.Value,
                                                        Power = (int)protPowerNud.Value,
                                                        Speed = (int)protSpeedNud.Value,
                                                        WeaponSlots = (int)enemiesWeaponSlotsNud.Value
                                                    },

                                                    new SinglecRectProperties
                                                    {
                                                        SourceRectangle = new EditorRect
                                                        {
                                                            X = (int)enemiesSrXNud.Value,
                                                            Y = (int)enemiesSrYNud.Value,
                                                            Width = (int)enemiesSrWidthNud.Value,
                                                            Height = (int)enemiesSrHeightNud.Value
                                                        },
                                                        CollisionRectangle = new EditorRect
                                                                               {
                                                                                   X = int.Parse(colR.SubItems[0].Text),
                                                                                   Y = int.Parse(colR.SubItems[1].Text),
                                                                                   Width = int.Parse(colR.SubItems[2].Text),
                                                                                   Height = int.Parse(colR.SubItems[3].Text)
                                                                               }
                                                    });
        }

        private void removeEnemyOpt_Click(object sender, EventArgs e)
        {
            if (enemiesLv.SelectedIndices.Count == 0) return;

            int id = int.Parse(enemiesLv.SelectedItems[0].SubItems[0].Text);

            presenter.EnemyPresenter.DeleteEnemy(id);

            enemiesLv.Items.RemoveAt(enemiesLv.SelectedIndices[0]);

            bIgnoreEvent = true;

            enemiesHpNud.Value = 0;
            enemiesPowerNud.Value = 0;
            enemiesSpeedNud.Value = 0;
            enemiesWeaponSlotsNud.Value = 0;
            enemiesHpNud.Value = 0;

            enemiesSrXNud.Value = 0;
            enemiesSrYNud.Value = 0;
            enemiesSrWidthNud.Value = 0;
            enemiesSrHeightNud.Value = 0;

            enemiesColRectsLv.Items.Clear();

            enemiesWeaponsLv.SelectedIndices.Clear();

            bIgnoreEvent = false;
        }

        private void addEnemySrcRectOpt_Click(object sender, EventArgs e)
        {
            if (enemiesLv.SelectedIndices.Count == 0)
            {
                MessageBox.Show(@"Select an enemy first!", Resources.GameEditorTitle);
                return;
            }

            addEnemySrcRectOpt.Checked = !addEnemySrcRectOpt.Checked;

            addEnemySrcRectOpt.BackColor = addEnemySrcRectOpt.Checked
                                                ? Color.LightBlue : SystemColors.Control;

            addEnemyColRectOpt.Checked = false;

            addEnemyColRectOpt.BackColor = SystemColors.Control;
        }

        private void addEnemyColRectOpt_Click(object sender, EventArgs e)
        {
            if (enemiesLv.SelectedIndices.Count == 0)
            {
                MessageBox.Show(@"Select an enemy first!", Resources.GameEditorTitle);
                return;
            }

            addEnemyColRectOpt.Checked = !addEnemyColRectOpt.Checked;

            addEnemyColRectOpt.BackColor = addEnemyColRectOpt.Checked
                                                ? Color.LightBlue : SystemColors.Control;

            addEnemySrcRectOpt.Checked = false;

            addEnemySrcRectOpt.BackColor = SystemColors.Control;
        }

        private void enemiesLv_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (enemiesLv.SelectedIndices.Count == 0) return;

            bDrawEnemyImg = true;
            bCanEnemyDrawRect = false;

            int id = int.Parse(enemiesLv.SelectedItems[0].SubItems[0].Text);

            Enemy enemy = presenter.EnemyPresenter.GetEnemy(id);

            bIgnoreEvent = true;

            enemiesHpNud.Value = enemy.Hp;
            enemiesPowerNud.Value = enemy.Power;
            enemiesSpeedNud.Value = enemy.Speed;
            enemiesWeaponSlotsNud.Value = enemy.WeaponSlots;

            enemiesSrXNud.Value = enemy.SourceRect.X;
            enemiesSrYNud.Value = enemy.SourceRect.Y;
            enemiesSrWidthNud.Value = enemy.SourceRect.Width;
            enemiesSrHeightNud.Value = enemy.SourceRect.Height;

            enemiesColRectsLv.Items.Clear();
            enemiesColRectsLv.Items.Add(new ListViewItem(new[]
                                                            {
                                                                enemy.CollisionRectangle.X.ToString(),
                                                                enemy.CollisionRectangle.Y.ToString(),
                                                                enemy.CollisionRectangle.Width.ToString(),
                                                                enemy.CollisionRectangle.Height.ToString()
                                                            }));

            bIgnoreEvent = false;

            enemyCanvasPnl.Invalidate();
        }

        private void setEnemySpriteOpt_Click(object sender, EventArgs e)
        {
            if (enemiesLv.SelectedIndices.Count == 0 ||
                enemiesSpritesLbx.SelectedIndex < 0) return;

            int id = int.Parse(enemiesLv.SelectedItems[0].SubItems[0].Text);

            presenter.EnemyPresenter.SetEnemySprite(id, enemiesSpritesLbx.SelectedItem.ToString());
        }

        private void enemiesHpNud_ValueChanged(object sender, EventArgs e)
        {
            if (enemiesLv.SelectedIndices.Count == 0 || bIgnoreEvent) return;

            int id = int.Parse(enemiesLv.SelectedItems[0].SubItems[0].Text);

            presenter.EnemyPresenter.SaveData(id, (int)enemiesHpNud.Value, (int)enemiesPowerNud.Value,
                 (int)enemiesSpeedNud.Value, (int)enemiesWeaponSlotsNud.Value);

            enemiesLv.SelectedItems[0].SubItems[1].Text = enemiesHpNud.Value.ToString();
        }

        private void enemiesPowerNud_ValueChanged(object sender, EventArgs e)
        {
            if (enemiesLv.SelectedIndices.Count == 0 || bIgnoreEvent) return;

            int id = int.Parse(enemiesLv.SelectedItems[0].SubItems[0].Text);

            presenter.EnemyPresenter.SaveData(id, (int)enemiesHpNud.Value, (int)enemiesPowerNud.Value,
                 (int)enemiesSpeedNud.Value, (int)enemiesWeaponSlotsNud.Value);

            enemiesLv.SelectedItems[0].SubItems[2].Text = enemiesPowerNud.Value.ToString();
        }

        private void enemiesSpeedNud_ValueChanged(object sender, EventArgs e)
        {
            if (enemiesLv.SelectedIndices.Count == 0 || bIgnoreEvent) return;

            int id = int.Parse(enemiesLv.SelectedItems[0].SubItems[0].Text);

            presenter.EnemyPresenter.SaveData(id, (int)enemiesHpNud.Value, (int)enemiesPowerNud.Value,
                 (int)enemiesSpeedNud.Value, (int)enemiesWeaponSlotsNud.Value);

            enemiesLv.SelectedItems[0].SubItems[3].Text = enemiesSpeedNud.Value.ToString();
        }

        private void enemiesWeaponSlotsNud_ValueChanged(object sender, EventArgs e)
        {
            if (enemiesLv.SelectedIndices.Count == 0 || bIgnoreEvent) return;

            int id = int.Parse(enemiesLv.SelectedItems[0].SubItems[0].Text);

            presenter.EnemyPresenter.SaveData(id, (int)enemiesHpNud.Value, (int)enemiesPowerNud.Value,
                 (int)enemiesSpeedNud.Value, (int)enemiesWeaponSlotsNud.Value);

            enemiesLv.SelectedItems[0].SubItems[4].Text = enemiesWeaponSlotsNud.Value.ToString();
        }

        private void enemiesSrXNud_ValueChanged(object sender, EventArgs e)
        {
            if (enemiesLv.SelectedIndices.Count == 0 || bIgnoreEvent) return;

            int id = int.Parse(enemiesLv.SelectedItems[0].SubItems[0].Text);

            presenter.EnemyPresenter.SetSourceRectangle(id, new EditorRect((int)enemiesSrXNud.Value,
                                                                           (int)enemiesSrYNud.Value,
                                                                           (int)enemiesSrWidthNud.Value,
                                                                           (int)enemiesSrHeightNud.Value));

            enemyCanvasPnl.Invalidate();
        }

        private void enemiesWidthNud_ValueChanged(object sender, EventArgs e)
        {
            if (enemiesLv.SelectedIndices.Count == 0 || bIgnoreEvent) return;

            int id = int.Parse(enemiesLv.SelectedItems[0].SubItems[0].Text);

            presenter.EnemyPresenter.SetSourceRectangle(id, new EditorRect((int)enemiesSrXNud.Value,
                                                                           (int)enemiesSrYNud.Value,
                                                                           (int)enemiesSrWidthNud.Value,
                                                                           (int)enemiesSrHeightNud.Value));

            enemyCanvasPnl.Invalidate();
        }

        private void enemiesSrYNud_ValueChanged(object sender, EventArgs e)
        {
            if (enemiesLv.SelectedIndices.Count == 0 || bIgnoreEvent) return;

            int id = int.Parse(enemiesLv.SelectedItems[0].SubItems[0].Text);

            presenter.EnemyPresenter.SetSourceRectangle(id, new EditorRect((int)enemiesSrXNud.Value,
                                                                           (int)enemiesSrYNud.Value,
                                                                           (int)enemiesSrWidthNud.Value,
                                                                           (int)enemiesSrHeightNud.Value));

            enemyCanvasPnl.Invalidate();
        }

        private void enemiesHeightNud_ValueChanged(object sender, EventArgs e)
        {
            if (enemiesLv.SelectedIndices.Count == 0 || bIgnoreEvent) return;

            int id = int.Parse(enemiesLv.SelectedItems[0].SubItems[0].Text);

            presenter.EnemyPresenter.SetSourceRectangle(id, new EditorRect((int)enemiesSrXNud.Value,
                                                                           (int)enemiesSrYNud.Value,
                                                                           (int)enemiesSrWidthNud.Value,
                                                                           (int)enemiesSrHeightNud.Value));

            enemyCanvasPnl.Invalidate();
        }

        private void enemiesColRectsLv_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (enemiesColRectsLv.SelectedIndices.Count == 0 || enemiesLv.SelectedIndices.Count == 0)
            {
                bIgnoreEvent = true;
                
                enemiesColRectXNud.Value = 0;
                enemiesColRectYNud.Value = 0;
                enemiesColRectWidthNud.Value = 0;
                enemiesColRectHeightNud.Value = 0;

                bIgnoreEvent = false;

                return;
            }

            bIgnoreEvent = true;

            enemiesColRectXNud.Value = decimal.Parse(enemiesColRectsLv.SelectedItems[0].SubItems[0].Text);
            enemiesColRectYNud.Value = decimal.Parse(enemiesColRectsLv.SelectedItems[0].SubItems[1].Text);
            enemiesColRectWidthNud.Value = decimal.Parse(enemiesColRectsLv.SelectedItems[0].SubItems[2].Text);
            enemiesColRectHeightNud.Value = decimal.Parse(enemiesColRectsLv.SelectedItems[0].SubItems[3].Text);

            bIgnoreEvent = false;
        }

        private void enemiesColRectXNud_ValueChanged(object sender, EventArgs e)
        {
            if (enemiesLv.SelectedIndices.Count == 0 || enemiesColRectsLv.SelectedIndices.Count == 0 || bIgnoreEvent) return;

            int id = int.Parse(enemiesLv.SelectedItems[0].SubItems[0].Text);

            presenter.EnemyPresenter.SetCollisionRectangle(id, new EditorRect((int)enemiesColRectXNud.Value,
                                                                           (int)enemiesColRectYNud.Value,
                                                                           (int)enemiesColRectWidthNud.Value,
                                                                           (int)enemiesColRectHeightNud.Value));

            enemiesColRectsLv.SelectedItems[0].SubItems[0].Text = enemiesColRectXNud.Value.ToString();
        }

        private void enemiesColRectYNud_ValueChanged(object sender, EventArgs e)
        {
            if (enemiesLv.SelectedIndices.Count == 0 || enemiesColRectsLv.SelectedIndices.Count == 0 || bIgnoreEvent) return;

            int id = int.Parse(enemiesLv.SelectedItems[0].SubItems[0].Text);

            presenter.EnemyPresenter.SetCollisionRectangle(id, new EditorRect((int)enemiesColRectXNud.Value,
                                                                           (int)enemiesColRectYNud.Value,
                                                                           (int)enemiesColRectWidthNud.Value,
                                                                           (int)enemiesColRectHeightNud.Value));

            enemiesColRectsLv.SelectedItems[0].SubItems[1].Text = enemiesColRectYNud.Value.ToString();
        }

        private void enemiesColRectWidthNud_ValueChanged(object sender, EventArgs e)
        {
            if (enemiesLv.SelectedIndices.Count == 0 || enemiesColRectsLv.SelectedIndices.Count == 0 || bIgnoreEvent) return;

            int id = int.Parse(enemiesLv.SelectedItems[0].SubItems[0].Text);

            presenter.EnemyPresenter.SetCollisionRectangle(id, new EditorRect((int)enemiesColRectXNud.Value,
                                                                           (int)enemiesColRectYNud.Value,
                                                                           (int)enemiesColRectWidthNud.Value,
                                                                           (int)enemiesColRectHeightNud.Value));

            enemiesColRectsLv.SelectedItems[0].SubItems[2].Text = enemiesColRectWidthNud.Value.ToString();
        }

        private void enemiesColRectHeight_ValueChanged(object sender, EventArgs e)
        {
            if (enemiesLv.SelectedIndices.Count == 0 || enemiesColRectsLv.SelectedIndices.Count == 0 || bIgnoreEvent) return;

            int id = int.Parse(enemiesLv.SelectedItems[0].SubItems[0].Text);

            presenter.EnemyPresenter.SetCollisionRectangle(id, new EditorRect((int)enemiesColRectXNud.Value,
                                                                           (int)enemiesColRectYNud.Value,
                                                                           (int)enemiesColRectWidthNud.Value,
                                                                           (int)enemiesColRectHeightNud.Value));

            enemiesColRectsLv.SelectedItems[0].SubItems[3].Text = enemiesColRectHeightNud.Value.ToString();
        }

        private void removeEnemyColRectBtn_Click(object sender, EventArgs e)
        {
            if (enemiesLv.SelectedIndices.Count == 0 || enemiesColRectsLv.SelectedIndices.Count == 0) return;

            int id = int.Parse(enemiesLv.SelectedItems[0].SubItems[0].Text);

            EditorRect colRect = presenter.EnemyPresenter.SetCollisionRectangle(id, EditorRect.Empty);

            enemiesColRectsLv.SelectedItems[0].SubItems[0].Text = colRect.X.ToString();
            enemiesColRectsLv.SelectedItems[0].SubItems[1].Text = colRect.Y.ToString();
            enemiesColRectsLv.SelectedItems[0].SubItems[2].Text = colRect.Width.ToString();
            enemiesColRectsLv.SelectedItems[0].SubItems[3].Text = colRect.Height.ToString();
        }

        private void enemiesWeaponsLv_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (enemiesWeaponsLv.SelectedIndices.Count == 0 || enemiesLv.SelectedIndices.Count == 0 || bIgnoreEvent) return;

            IEnumerable<int> weaponIds = from ListViewItem item in enemiesWeaponsLv.Items
                                   select int.Parse(item.SubItems[0].Text);

            int id = int.Parse(enemiesLv.SelectedItems[0].SubItems[0].Text);

            string errMsg;
            if(!presenter.EnemyPresenter.AddWeapons(id, weaponIds, out errMsg))
            {
                MessageBox.Show(errMsg, Resources.GameEditorTitle);
            }
        }

        private void enemyCanvasPnl_Paint(object sender, PaintEventArgs e)
        {
            int index = enemiesLv.SelectedIndices.Count > 0 ? enemiesLv.SelectedIndices[0] : -1;
            Enemy enemy = null;
            if (index > -1)
            {
                int id = int.Parse(enemiesLv.SelectedItems[0].SubItems[0].Text);
                enemy = presenter.EnemyPresenter.GetEnemy(id);
            }

            // draw image
            if (bDrawEnemyImg)
            {
                if (enemy == null || string.IsNullOrEmpty(enemy.TextureName))
                    return;

                e.Graphics.DrawImage(Image.FromFile(enemy.TextureName), Point.Empty);
            }
            else
            {
                if (enemiesSpritesLbx.SelectedIndex >= 0)
                    e.Graphics.DrawImage(Image.FromFile(protSpritesLbx.Items[enemiesSpritesLbx.SelectedIndex].ToString()), Point.Empty);
            }

            // draw rectangles
            if (!bCanEnemyDrawRect && enemy != null)
            {
                curSourceRect = enemy.SourceRect;
                    
                e.Graphics.DrawRectangle(redPen, enemy.CollisionRectangle);
            }
            else
            {
                e.Graphics.DrawRectangle(redPen, curColRect);
            }

            e.Graphics.DrawRectangle(bluePen, curSourceRect);

        }

        private void enemyCanvasPnl_MouseDown(object sender, MouseEventArgs e)
        {
            bCanEnemyDrawRect = true;

            Point mousePos = enemyCanvasPnl.PointToClient(Cursor.Position);

            if (addEnemySrcRectOpt.Checked)
                curSourceRect.Location = mousePos;
            else if (addEnemyColRectOpt.Checked)
                curColRect.Location = mousePos;
        }

        private void enemyCanvasPnl_MouseMove(object sender, MouseEventArgs e)
        {
            if (!bCanEnemyDrawRect || e.Button != MouseButtons.Left) return;

            Point mousePos = enemyCanvasPnl.PointToClient(Cursor.Position);

            if (addEnemySrcRectOpt.Checked)
            {
                curSourceRect.Width = mousePos.X - curSourceRect.X;
                curSourceRect.Height = mousePos.Y - curSourceRect.Y;
            }
            else if (addEnemyColRectOpt.Checked)
            {
                curColRect.Width = mousePos.X - curColRect.X;
                curColRect.Height = mousePos.Y - curColRect.Y;
            }

            enemyCanvasPnl.Invalidate();
        }

        private void enemyCanvasPnl_MouseUp(object sender, MouseEventArgs e)
        {
            bCanEnemyDrawRect = false;

            if (enemiesLv.SelectedIndices.Count == 0) return;

            int id = int.Parse(enemiesLv.SelectedItems[0].SubItems[0].Text);

            presenter.EnemyPresenter.SetSourceRectangle(id, curSourceRect);

            if (!curColRect.IsEmpty)
            {
                presenter.EnemyPresenter.SetCollisionRectangle(id, curColRect);

                curColRect = Rectangle.Empty;
            }
        }
        #endregion


        #region MiniBosses
        private void addMiniBossOpt_Click(object sender, EventArgs e)
        {
            MiniBossEnemy mnb = presenter.MinibossPresenter.AddMiniBossEnemy();

            miniBossLv.Items.Add(new ListViewItem(new[]
                                                    {
                                                        mnb.ID.ToString(),
                                                        mnb.Hp.ToString(),
                                                        mnb.Power.ToString(),
                                                        mnb.Speed.ToString(),
                                                        mnb.WeaponSlots.ToString(),
                                                    }));
        }

        private void saveMinibossEditOpt_Click(object sender, EventArgs e)
        {
            if (miniBossLv.SelectedIndices.Count == 0) return;

            int id = int.Parse(miniBossLv.SelectedItems[0].SubItems[0].Text);

            var colR = miniBossColRectsLv.Items[0];

            presenter.MinibossPresenter.SaveData(id,

                                                    new AircraftStats
                                                    {
                                                        Hp = (int)miniBossHpNud.Value,
                                                        Power = (int)miniBossPowerNud.Value,
                                                        Speed = (int)miniBossSpeedNud.Value,
                                                        WeaponSlots = (int)miniBossWeaponSlotsNud.Value
                                                    },

                                                    new SinglecRectProperties
                                                    {
                                                        SourceRectangle = new EditorRect
                                                        {
                                                            X = (int)miniBossSrXNud.Value,
                                                            Y = (int)miniBossSrYNud.Value,
                                                            Width = (int)miniBossSrWidthNud.Value,
                                                            Height = (int)miniBossSrHeightNud.Value
                                                        },
                                                        CollisionRectangle = new EditorRect
                                                        {
                                                            X = int.Parse(colR.SubItems[0].Text),
                                                            Y = int.Parse(colR.SubItems[1].Text),
                                                            Width = int.Parse(colR.SubItems[2].Text),
                                                            Height = int.Parse(colR.SubItems[3].Text)
                                                        }
                                                    });
        }

        private void removeMinibossOpt_Click(object sender, EventArgs e)
        {
            if (miniBossLv.SelectedIndices.Count == 0) return;

            int id = int.Parse(miniBossLv.SelectedItems[0].SubItems[0].Text);

            presenter.MinibossPresenter.DeleteMiniBoss(id);

            miniBossLv.Items.RemoveAt(miniBossLv.SelectedIndices[0]);

            bIgnoreEvent = true;

            miniBossHpNud.Value = 0;
            miniBossPowerNud.Value = 0;
            miniBossSpeedNud.Value = 0;
            miniBossWeaponSlotsNud.Value = 0;
            miniBossHpNud.Value = 0;

            miniBossSrXNud.Value = 0;
            miniBossSrYNud.Value = 0;
            miniBossSrWidthNud.Value = 0;
            miniBossSrHeightNud.Value = 0;

            miniBossColRectsLv.Items.Clear();

            miniBossWeaponsLv.SelectedIndices.Clear();

            bIgnoreEvent = false;
        }

        private void addMinibossSrcRectOpt_Click(object sender, EventArgs e)
        {
            if (miniBossLv.SelectedIndices.Count == 0)
            {
                MessageBox.Show(@"Select a miniboss first!", Resources.GameEditorTitle);
                return;
            }

            addMinibossSrcRectOpt.Checked = !addMinibossSrcRectOpt.Checked;

            addMinibossSrcRectOpt.BackColor = addMinibossSrcRectOpt.Checked
                                                ? Color.LightBlue : SystemColors.Control;

            addMinibossColRectOpt.Checked = false;

            addMinibossColRectOpt.BackColor = SystemColors.Control;
        }

        private void addMinibossColRectOpt_Click(object sender, EventArgs e)
        {
            if (miniBossLv.SelectedIndices.Count == 0)
            {
                MessageBox.Show(@"Select a miniboss first!", Resources.GameEditorTitle);
                return;
            }

            addMinibossColRectOpt.Checked = !addMinibossColRectOpt.Checked;

            addMinibossColRectOpt.BackColor = addMinibossColRectOpt.Checked
                                                ? Color.LightBlue : SystemColors.Control;

            addMinibossSrcRectOpt.Checked = false;

            addMinibossSrcRectOpt.BackColor = SystemColors.Control;
        }

        private void miniBossLv_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (miniBossLv.SelectedIndices.Count == 0) return;

            bDrawMinibossImg = true;
            bCanMinibossDrawRect = false;

            int id = int.Parse(miniBossLv.SelectedItems[0].SubItems[0].Text);

            MiniBossEnemy mnb = presenter.MinibossPresenter.GetMiniboss(id);

            bIgnoreEvent = true;

            miniBossHpNud.Value = mnb.Hp;
            miniBossPowerNud.Value = mnb.Power;
            miniBossSpeedNud.Value = mnb.Speed;
            miniBossWeaponSlotsNud.Value = mnb.WeaponSlots;

            miniBossSrXNud.Value = mnb.SourceRect.X;
            miniBossSrYNud.Value = mnb.SourceRect.Y;
            miniBossSrWidthNud.Value = mnb.SourceRect.Width;
            miniBossSrHeightNud.Value = mnb.SourceRect.Height;

            miniBossColRectsLv.Items.Clear();
            miniBossColRectsLv.Items.Add(new ListViewItem(new[]
                                                            {
                                                                mnb.CollisionRectangle.X.ToString(),
                                                                mnb.CollisionRectangle.Y.ToString(),
                                                                mnb.CollisionRectangle.Width.ToString(),
                                                                mnb.CollisionRectangle.Height.ToString()
                                                            }));

            bIgnoreEvent = false;

            miniBossCanvasPnl.Invalidate();
        }

        private void addMiniBossSpriteOpt_Click(object sender, EventArgs e)
        {
            if (miniBossLv.SelectedIndices.Count == 0 ||
               miniBossSpritesLbx.SelectedIndex < 0) return;

            int id = int.Parse(miniBossLv.SelectedItems[0].SubItems[0].Text);

            presenter.MinibossPresenter.SetMiniBossSprite(id, miniBossSpritesLbx.SelectedItem.ToString());
        }

        private void miniBossSpritesLbx_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (miniBossLv.SelectedIndices.Count == 0 ||
               miniBossSpritesLbx.SelectedIndex < 0) return;

            int id = int.Parse(miniBossLv.SelectedItems[0].SubItems[0].Text);

            presenter.MinibossPresenter.SetMiniBossSprite(id, miniBossSpritesLbx.SelectedItem.ToString());
        }

        private void miniBossHpNud_ValueChanged(object sender, EventArgs e)
        {
            if (miniBossLv.SelectedIndices.Count == 0 || bIgnoreEvent) return;

            int id = int.Parse(miniBossLv.SelectedItems[0].SubItems[0].Text);

            presenter.MinibossPresenter.SaveData(id, (int)miniBossHpNud.Value, (int)miniBossPowerNud.Value,
                 (int)miniBossSpeedNud.Value, (int)miniBossWeaponSlotsNud.Value);

            miniBossLv.SelectedItems[0].SubItems[1].Text = miniBossHpNud.Value.ToString();
        }

        private void miniBossSpeedNud_ValueChanged(object sender, EventArgs e)
        {
            if (miniBossLv.SelectedIndices.Count == 0 || bIgnoreEvent) return;

            int id = int.Parse(miniBossLv.SelectedItems[0].SubItems[0].Text);

            presenter.MinibossPresenter.SaveData(id, (int)miniBossHpNud.Value, (int)miniBossPowerNud.Value,
                 (int)miniBossSpeedNud.Value, (int)miniBossWeaponSlotsNud.Value);

            miniBossLv.SelectedItems[0].SubItems[3].Text = miniBossSpeedNud.Value.ToString();
        }

        private void miniBossWeaponSlotsNud_ValueChanged(object sender, EventArgs e)
        {
            if (miniBossLv.SelectedIndices.Count == 0 || bIgnoreEvent) return;

            int id = int.Parse(miniBossLv.SelectedItems[0].SubItems[0].Text);

            presenter.MinibossPresenter.SaveData(id, (int)miniBossHpNud.Value, (int)miniBossPowerNud.Value,
                 (int)miniBossSpeedNud.Value, (int)miniBossWeaponSlotsNud.Value);

            miniBossLv.SelectedItems[0].SubItems[4].Text = miniBossWeaponSlotsNud.Value.ToString();
        }

        private void miniBossSrXNud_ValueChanged(object sender, EventArgs e)
        {
            if (miniBossLv.SelectedIndices.Count == 0 || bIgnoreEvent) return;

            int id = int.Parse(miniBossLv.SelectedItems[0].SubItems[0].Text);

            presenter.MinibossPresenter.SetSourceRectangle(id, new EditorRect((int)miniBossSrXNud.Value,
                                                                           (int)miniBossSrYNud.Value,
                                                                           (int)miniBossSrWidthNud.Value,
                                                                           (int)miniBossSrHeightNud.Value));

            miniBossCanvasPnl.Invalidate();
        }

        private void minibossSrWidthNud_ValueChanged(object sender, EventArgs e)
        {
            if (miniBossLv.SelectedIndices.Count == 0 || bIgnoreEvent) return;

            int id = int.Parse(miniBossLv.SelectedItems[0].SubItems[0].Text);

            presenter.MinibossPresenter.SetSourceRectangle(id, new EditorRect((int)miniBossSrXNud.Value,
                                                                           (int)miniBossSrYNud.Value,
                                                                           (int)miniBossSrWidthNud.Value,
                                                                           (int)miniBossSrHeightNud.Value));

            miniBossCanvasPnl.Invalidate();
        }

        private void miniBossSrYNud_ValueChanged(object sender, EventArgs e)
        {
            if (miniBossLv.SelectedIndices.Count == 0 || bIgnoreEvent) return;

            int id = int.Parse(miniBossLv.SelectedItems[0].SubItems[0].Text);

            presenter.MinibossPresenter.SetSourceRectangle(id, new EditorRect((int)miniBossSrXNud.Value,
                                                                           (int)miniBossSrYNud.Value,
                                                                           (int)miniBossSrWidthNud.Value,
                                                                           (int)miniBossSrHeightNud.Value));

            miniBossCanvasPnl.Invalidate();
        }

        private void miniBossSrHeightNud_ValueChanged(object sender, EventArgs e)
        {
            if (miniBossLv.SelectedIndices.Count == 0 || bIgnoreEvent) return;

            int id = int.Parse(miniBossLv.SelectedItems[0].SubItems[0].Text);

            presenter.MinibossPresenter.SetSourceRectangle(id, new EditorRect((int)miniBossSrXNud.Value,
                                                                           (int)miniBossSrYNud.Value,
                                                                           (int)miniBossSrWidthNud.Value,
                                                                           (int)miniBossSrHeightNud.Value));

            miniBossCanvasPnl.Invalidate();
        }

        private void miniBossColRectsLv_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (miniBossColRectsLv.SelectedIndices.Count == 0 || miniBossLv.SelectedIndices.Count == 0)
            {
                bIgnoreEvent = true;

                miniBossCrXNud.Value = 0;
                miniBossCrYNud.Value = 0;
                miniBossCrWidthNud.Value = 0;
                miniBossCrHeightNud.Value = 0;

                bIgnoreEvent = false;

                return;
            }

            bIgnoreEvent = true;

            miniBossCrXNud.Value = decimal.Parse(miniBossColRectsLv.SelectedItems[0].SubItems[0].Text);
            miniBossCrYNud.Value = decimal.Parse(miniBossColRectsLv.SelectedItems[0].SubItems[1].Text);
            miniBossCrWidthNud.Value = decimal.Parse(miniBossColRectsLv.SelectedItems[0].SubItems[2].Text);
            miniBossCrHeightNud.Value = decimal.Parse(miniBossColRectsLv.SelectedItems[0].SubItems[3].Text);

            bIgnoreEvent = false;
        }

        private void miniBossCrXNud_ValueChanged(object sender, EventArgs e)
        {
            if (miniBossLv.SelectedIndices.Count == 0 || miniBossColRectsLv.SelectedIndices.Count == 0 || bIgnoreEvent) return;

            int id = int.Parse(miniBossLv.SelectedItems[0].SubItems[0].Text);

            presenter.MinibossPresenter.SetCollisionRectangle(id, new EditorRect((int)miniBossCrXNud.Value,
                                                                           (int)miniBossCrYNud.Value,
                                                                           (int)miniBossCrWidthNud.Value,
                                                                           (int)miniBossCrHeightNud.Value));

            miniBossColRectsLv.SelectedItems[0].SubItems[0].Text = miniBossCrXNud.Value.ToString();
        }

        private void miniBossCrYNud_ValueChanged(object sender, EventArgs e)
        {
            if (miniBossLv.SelectedIndices.Count == 0 || miniBossColRectsLv.SelectedIndices.Count == 0 || bIgnoreEvent) return;

            int id = int.Parse(miniBossLv.SelectedItems[0].SubItems[0].Text);

            presenter.MinibossPresenter.SetCollisionRectangle(id, new EditorRect((int)miniBossCrXNud.Value,
                                                                           (int)miniBossCrYNud.Value,
                                                                           (int)miniBossCrWidthNud.Value,
                                                                           (int)miniBossCrHeightNud.Value));

            miniBossColRectsLv.SelectedItems[0].SubItems[1].Text = miniBossCrYNud.Value.ToString();
        }

        private void miniBossCrWidthNud_ValueChanged(object sender, EventArgs e)
        {
            if (miniBossLv.SelectedIndices.Count == 0 || miniBossColRectsLv.SelectedIndices.Count == 0 || bIgnoreEvent) return;

            int id = int.Parse(miniBossLv.SelectedItems[0].SubItems[0].Text);

            presenter.MinibossPresenter.SetCollisionRectangle(id, new EditorRect((int)miniBossCrXNud.Value,
                                                                           (int)miniBossCrYNud.Value,
                                                                           (int)miniBossCrWidthNud.Value,
                                                                           (int)miniBossCrHeightNud.Value));

            miniBossColRectsLv.SelectedItems[0].SubItems[2].Text = miniBossCrWidthNud.Value.ToString();
        }

        private void miniBossCrHeightNud_ValueChanged(object sender, EventArgs e)
        {
            if (miniBossLv.SelectedIndices.Count == 0 || miniBossColRectsLv.SelectedIndices.Count == 0 || bIgnoreEvent) return;

            int id = int.Parse(miniBossLv.SelectedItems[0].SubItems[0].Text);

            presenter.MinibossPresenter.SetCollisionRectangle(id, new EditorRect((int)miniBossCrXNud.Value,
                                                                           (int)miniBossCrYNud.Value,
                                                                           (int)miniBossCrWidthNud.Value,
                                                                           (int)miniBossCrHeightNud.Value));

            miniBossColRectsLv.SelectedItems[0].SubItems[3].Text = miniBossCrHeightNud.Value.ToString();
        }

        private void miniBossRemoveColRectBtn_Click(object sender, EventArgs e)
        {
            if (miniBossLv.SelectedIndices.Count == 0 || miniBossColRectsLv.SelectedIndices.Count == 0) return;

            int id = int.Parse(miniBossLv.SelectedItems[0].SubItems[0].Text);

            EditorRect colRect = presenter.MinibossPresenter.SetCollisionRectangle(id, EditorRect.Empty);

            miniBossColRectsLv.SelectedItems[0].SubItems[0].Text = colRect.X.ToString();
            miniBossColRectsLv.SelectedItems[0].SubItems[1].Text = colRect.Y.ToString();
            miniBossColRectsLv.SelectedItems[0].SubItems[2].Text = colRect.Width.ToString();
            miniBossColRectsLv.SelectedItems[0].SubItems[3].Text = colRect.Height.ToString();
        }

        private void miniBossWeaponsLv_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (miniBossWeaponsLv.SelectedIndices.Count == 0 || miniBossLv.SelectedIndices.Count == 0 || bIgnoreEvent) return;

            IEnumerable<int> weaponIds = from ListViewItem item in miniBossWeaponsLv.Items
                                         select int.Parse(item.SubItems[0].Text);

            int id = int.Parse(miniBossLv.SelectedItems[0].SubItems[0].Text);

            string errMsg;
            if (!presenter.MinibossPresenter.AddWeapons(id, weaponIds, out errMsg))
            {
                MessageBox.Show(errMsg, Resources.GameEditorTitle);
            }
        }

        private void miniBossCanvasPnl_Paint(object sender, PaintEventArgs e)
        {
            int index = miniBossLv.SelectedIndices.Count > 0 ? miniBossLv.SelectedIndices[0] : -1;
            MiniBossEnemy miniBoss = null;
            if (index > -1)
            {
                int id = int.Parse(miniBossLv.SelectedItems[0].SubItems[0].Text);
                miniBoss = presenter.MinibossPresenter.GetMiniboss(id);
            }

            // draw image
            if (bDrawMinibossImg)
            {
                if (miniBoss == null || string.IsNullOrEmpty(miniBoss.TextureName))
                    return;

                e.Graphics.DrawImage(Image.FromFile(miniBoss.TextureName), Point.Empty);
            }
            else
            {
                if (miniBossSpritesLbx.SelectedIndex >= 0)
                    e.Graphics.DrawImage(Image.FromFile(protSpritesLbx.Items[miniBossSpritesLbx.SelectedIndex].ToString()), Point.Empty);
            }

            // draw rectangles
            if (!bCanMinibossDrawRect && miniBoss != null)
            {
                curSourceRect = miniBoss.SourceRect;

                e.Graphics.DrawRectangle(redPen, miniBoss.CollisionRectangle);
            }
            else
            {
                e.Graphics.DrawRectangle(redPen, curColRect);
            }

            e.Graphics.DrawRectangle(bluePen, curSourceRect);

        }

        private void minibossCanvasPnl_MouseDown(object sender, MouseEventArgs e)
        {
            bCanMinibossDrawRect = true;

            Point mousePos = miniBossCanvasPnl.PointToClient(Cursor.Position);

            if (addMinibossSrcRectOpt.Checked)
                curSourceRect.Location = mousePos;
            else if (addMinibossColRectOpt.Checked)
                curColRect.Location = mousePos;
        }

        private void minibossCanvasPnl_MouseMove(object sender, MouseEventArgs e)
        {
            if (!bCanMinibossDrawRect || e.Button != MouseButtons.Left) return;

            Point mousePos = miniBossCanvasPnl.PointToClient(Cursor.Position);

            if (addMinibossSrcRectOpt.Checked)
            {
                curSourceRect.Width = mousePos.X - curSourceRect.X;
                curSourceRect.Height = mousePos.Y - curSourceRect.Y;
            }
            else if (addMinibossSrcRectOpt.Checked)
            {
                curColRect.Width = mousePos.X - curColRect.X;
                curColRect.Height = mousePos.Y - curColRect.Y;
            }

            miniBossCanvasPnl.Invalidate();
        }

        private void minibossCanvasPnl_MouseUp(object sender, MouseEventArgs e)
        {
            bCanMinibossDrawRect = false;

            if (miniBossLv.SelectedIndices.Count == 0) return;

            int id = int.Parse(miniBossLv.SelectedItems[0].SubItems[0].Text);

            presenter.MinibossPresenter.SetSourceRectangle(id, curSourceRect);

            if (!curColRect.IsEmpty)
            {
                presenter.MinibossPresenter.SetCollisionRectangle(id, curColRect);

                curColRect = Rectangle.Empty;
            }
        }
        #endregion


        #region Bosses
        private void addBossOpt_Click(object sender, EventArgs e)
        {
            BossEnemy boss = presenter.BossPresenter.AddBoss();
            bossLv.Items.Add(new ListViewItem(new[]
                                                  {
                                                      boss.ID.ToString(),
                                                      boss.Hp.ToString(),
                                                      boss.Power.ToString(),
                                                      boss.Speed.ToString(),
                                                      boss.WeaponSlots.ToString()
                                                  }));
        }

        private void saveBossEditOpt_Click(object sender, EventArgs e)
        {
            if (bossLv.SelectedIndices.Count == 0) return;

            int id = int.Parse(bossLv.SelectedItems[0].SubItems[0].Text);

            string errMsg;

            presenter.BossPresenter.Save(id,
                                         new AircraftStats
                                             {
                                                 Hp = int.Parse(bossLv.SelectedItems[0].SubItems[1].Text),
                                                 Power = int.Parse(bossLv.SelectedItems[0].SubItems[2].Text),
                                                 Speed = int.Parse(bossLv.SelectedItems[0].SubItems[3].Text),
                                                 WeaponSlots = int.Parse(bossLv.SelectedItems[0].SubItems[4].Text)
                                             },
                                         new RectangleProperties
                                             {
                                                 SourceRectangle = new EditorRect
                                                                       {
                                                                           X = (int) bossSrXNud.Value,
                                                                           Y = (int) bossSrYNud.Value,
                                                                           Width = (int) bossSrWidthNud.Value,
                                                                           Height = (int) bossSrHeightNud.Value
                                                                       },
                                                 CollisionRectangles = (from ListViewItem r in bossColRectsLv.Items
                                                                        select new EditorRect
                                                                                   {
                                                                                       X = int.Parse(r.SubItems[0].Text),
                                                                                       Y = int.Parse(r.SubItems[1].Text),
                                                                                       Width =
                                                                                           int.Parse(r.SubItems[2].Text),
                                                                                       Height =
                                                                                           int.Parse(r.SubItems[3].Text)
                                                                                   }).ToList()
                                             },

                                         from ListViewItem w in bossWeaponsLv.Items select int.Parse(w.SubItems[0].Text),
                                         out errMsg);

            if(errMsg != string.Empty)
                MessageBox.Show(errMsg, Resources.GameEditorTitle);
        }

        private void removeBossOpt_Click(object sender, EventArgs e)
        {
            if (bossLv.SelectedIndices.Count == 0) return;

            int id = int.Parse(bossLv.SelectedItems[0].SubItems[0].Text);
            presenter.BossPresenter.Remove(id);
        }

        private void addBossSourceRectOpt_Click(object sender, EventArgs e)
        {
            if (bossLv.SelectedIndices.Count == 0) return;

            int id = int.Parse(bossLv.SelectedItems[0].SubItems[0].Text);

            presenter.BossPresenter.AddSourceRectange(id, curSourceRect);
        }

        private void addBossColRectOpt_Click(object sender, EventArgs e)
        {
            if (bossLv.SelectedIndices.Count == 0) return;

            int id = int.Parse(bossLv.SelectedItems[0].SubItems[0].Text);

            presenter.BossPresenter.AddCollisionRectangle(id, curColRect);
        }

        private void addBossSpriteOpt_Click(object sender, EventArgs e)
        {
            if (bossLv.SelectedIndices.Count == 0 || bossSpritesLbx.SelectedIndex < 0) return;

            int id = int.Parse(bossLv.SelectedItems[0].SubItems[0].Text);

            presenter.BossPresenter.SetSpriteImage(id, (string) bossSpritesLbx.Items[bossSpritesLbx.SelectedIndex]);
        }

        private void bossSpritesLbx_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (bossLv.SelectedIndices.Count == 0 || bossSpritesLbx.SelectedIndex < 0) return;

            int id = int.Parse(bossLv.SelectedItems[0].SubItems[0].Text);

            presenter.BossPresenter.SetSpriteImage(id, miniBossSpritesLbx.SelectedItem.ToString());
        }

        private void bossHpNud_ValueChanged(object sender, EventArgs e)
        {
            if (bossLv.SelectedIndices.Count == 0 || bIgnoreEvent) return;

            int id = int.Parse(bossLv.SelectedItems[0].SubItems[0].Text);

            presenter.BossPresenter.Save(id, (int)bossHpNud.Value, (int)bossPowerNud.Value,
                 (int)bossSpeedNud.Value, (int)bossWeaponSlotsNud.Value);

            bossLv.SelectedItems[0].SubItems[1].Text = bossHpNud.Value.ToString();
        }

        private void bossPowerNud_ValueChanged(object sender, EventArgs e)
        {
            if (bossLv.SelectedIndices.Count == 0 || bIgnoreEvent) return;

            int id = int.Parse(bossLv.SelectedItems[0].SubItems[0].Text);

            presenter.BossPresenter.Save(id, (int)bossHpNud.Value, (int)bossPowerNud.Value,
                 (int)bossSpeedNud.Value, (int)bossWeaponSlotsNud.Value);

            bossLv.SelectedItems[0].SubItems[2].Text = bossPowerNud.Value.ToString();
        }

        private void bossSpeedNud_ValueChanged(object sender, EventArgs e)
        {
            if (bossLv.SelectedIndices.Count == 0 || bIgnoreEvent) return;

            int id = int.Parse(bossLv.SelectedItems[0].SubItems[0].Text);

            presenter.BossPresenter.Save(id, (int)bossHpNud.Value, (int)bossPowerNud.Value,
                 (int)bossSpeedNud.Value, (int)bossWeaponSlotsNud.Value);

            bossLv.SelectedItems[0].SubItems[3].Text = bossSpeedNud.Value.ToString();
        }

        private void bossWeaponSlotsNud_ValueChanged(object sender, EventArgs e)
        {
            if (bossLv.SelectedIndices.Count == 0 || bIgnoreEvent) return;

            int id = int.Parse(bossLv.SelectedItems[0].SubItems[0].Text);

            presenter.BossPresenter.Save(id, (int)bossHpNud.Value, (int)bossPowerNud.Value,
                 (int)bossSpeedNud.Value, (int)bossWeaponSlotsNud.Value);

            bossLv.SelectedItems[0].SubItems[4].Text = bossWeaponSlotsNud.Value.ToString();
        }

        private void bossSrXNud_ValueChanged(object sender, EventArgs e)
        {
            if (bossLv.SelectedIndices.Count == 0 || bIgnoreEvent) return;

            int id = int.Parse(bossLv.SelectedItems[0].SubItems[0].Text);

            presenter.BossPresenter.SetSourceRectangle(id, new EditorRect
                                                                {
                                                                    X = (int)bossSrXNud.Value,
                                                                    Y = (int)bossSrYNud.Value,
                                                                    Width = (int)bossSrWidthNud.Value,
                                                                    Height = (int)bossSrHeightNud.Value
                                                                });
        }

        private void bossSrYNud_ValueChanged(object sender, EventArgs e)
        {
            if (bossLv.SelectedIndices.Count == 0 || bIgnoreEvent) return;

            int id = int.Parse(bossLv.SelectedItems[0].SubItems[0].Text);

            presenter.BossPresenter.SetSourceRectangle(id, new EditorRect
            {
                X = (int)bossSrXNud.Value,
                Y = (int)bossSrYNud.Value,
                Width = (int)bossSrWidthNud.Value,
                Height = (int)bossSrHeightNud.Value
            });
        }

        private void bossSrWidthNud_ValueChanged(object sender, EventArgs e)
        {
            if (bossLv.SelectedIndices.Count == 0 || bIgnoreEvent) return;

            int id = int.Parse(bossLv.SelectedItems[0].SubItems[0].Text);

            presenter.BossPresenter.SetSourceRectangle(id, new EditorRect
            {
                X = (int)bossSrXNud.Value,
                Y = (int)bossSrYNud.Value,
                Width = (int)bossSrWidthNud.Value,
                Height = (int)bossSrHeightNud.Value
            });
        }

        private void bossSrHeightNud_ValueChanged(object sender, EventArgs e)
        {
            if (bossLv.SelectedIndices.Count == 0 || bIgnoreEvent) return;

            int id = int.Parse(bossLv.SelectedItems[0].SubItems[0].Text);

            presenter.BossPresenter.SetSourceRectangle(id, new EditorRect
            {
                X = (int)bossSrXNud.Value,
                Y = (int)bossSrYNud.Value,
                Width = (int)bossSrWidthNud.Value,
                Height = (int)bossSrHeightNud.Value
            });
        }

        private void bossColRectsLv_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (bossColRectsLv.SelectedIndices.Count == 0 || bossLv.SelectedIndices.Count == 0) return;

            bIgnoreEvent = true;
            bossCrXNud.Value = decimal.Parse(bossColRectsLv.SelectedItems[0].SubItems[0].Text);
            bossCrYNud.Value = decimal.Parse(bossColRectsLv.SelectedItems[0].SubItems[1].Text);
            bossCrHeightNud.Value = decimal.Parse(bossColRectsLv.SelectedItems[0].SubItems[2].Text);
            bossCrWidthNud.Value = decimal.Parse(bossColRectsLv.SelectedItems[0].SubItems[3].Text);
            bIgnoreEvent = false;
        }

        private void bossCrXNud_ValueChanged(object sender, EventArgs e)
        {
            if (bossColRectsLv.SelectedIndices.Count == 0 || bossLv.SelectedIndices.Count == 0 || bIgnoreEvent) return;

            int id = int.Parse(bossLv.SelectedItems[0].SubItems[0].Text);
            int colRIndex = bossColRectsLv.SelectedIndices[0];

            presenter.BossPresenter.SetCollisionRectangle(id, colRIndex, new EditorRect
                                                                            {
                                                                                X = (int)bossCrXNud.Value,
                                                                                Y = (int)bossCrYNud.Value,
                                                                                Width = (int)bossCrWidthNud.Value,
                                                                                Height = (int)bossCrHeightNud.Value
                                                                            });

            bossColRectsLv.SelectedItems[0].SubItems[0].Text = bossCrXNud.Value.ToString();

            bossCanvasPnl.Invalidate();
        }

        private void bossCrYNud_ValueChanged(object sender, EventArgs e)
        {
            if (bossColRectsLv.SelectedIndices.Count == 0 || bossLv.SelectedIndices.Count == 0 || bIgnoreEvent) return;

            int id = int.Parse(bossLv.SelectedItems[0].SubItems[0].Text);
            int colRIndex = bossColRectsLv.SelectedIndices[0];

            presenter.BossPresenter.SetCollisionRectangle(id, colRIndex, new EditorRect
            {
                X = (int)bossCrXNud.Value,
                Y = (int)bossCrYNud.Value,
                Width = (int)bossCrWidthNud.Value,
                Height = (int)bossCrHeightNud.Value
            });

            bossColRectsLv.SelectedItems[0].SubItems[1].Text = bossCrYNud.Value.ToString();

            bossCanvasPnl.Invalidate();
        }

        private void bossCrWidthNud_ValueChanged(object sender, EventArgs e)
        {
            if (bossColRectsLv.SelectedIndices.Count == 0 || bossLv.SelectedIndices.Count == 0 || bIgnoreEvent) return;

            int id = int.Parse(bossLv.SelectedItems[0].SubItems[0].Text);
            int colRIndex = bossColRectsLv.SelectedIndices[0];

            presenter.BossPresenter.SetCollisionRectangle(id, colRIndex, new EditorRect
            {
                X = (int)bossCrXNud.Value,
                Y = (int)bossCrYNud.Value,
                Width = (int)bossCrWidthNud.Value,
                Height = (int)bossCrHeightNud.Value
            });

            bossColRectsLv.SelectedItems[0].SubItems[2].Text = bossCrWidthNud.Value.ToString();

            bossCanvasPnl.Invalidate();
        }

        private void bossCrHeightNud_ValueChanged(object sender, EventArgs e)
        {
            if (bossColRectsLv.SelectedIndices.Count == 0 || bossLv.SelectedIndices.Count == 0 || bIgnoreEvent) return;

            int id = int.Parse(bossLv.SelectedItems[0].SubItems[0].Text);
            int colRIndex = bossColRectsLv.SelectedIndices[0];

            presenter.BossPresenter.SetCollisionRectangle(id, colRIndex, new EditorRect
            {
                X = (int)bossCrXNud.Value,
                Y = (int)bossCrYNud.Value,
                Width = (int)bossCrWidthNud.Value,
                Height = (int)bossCrHeightNud.Value
            });

            bossColRectsLv.SelectedItems[0].SubItems[3].Text = bossCrHeightNud.Value.ToString();

            bossCanvasPnl.Invalidate();
        }

        private void removeBossColRectBtn_Click(object sender, EventArgs e)
        {
            if (bossColRectsLv.SelectedIndices.Count == 0 || bossLv.SelectedIndices.Count == 0) return;

            int id = int.Parse(bossLv.SelectedItems[0].SubItems[0].Text);
            int colRIndex = bossColRectsLv.SelectedIndices[0];

            presenter.BossPresenter.RemoveCollisionRectangle(id, colRIndex);

            bossCanvasPnl.Invalidate();
        }

        private void bossWeaponsLv_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (bossLv.SelectedIndices.Count == 0) return;


        }

        private void bossCanvasPnl_Paint(object sender, PaintEventArgs e)
        {
            int selectedBossIndex = bossLv.SelectedIndices.Count > 0 ? bossLv.SelectedIndices[0] : -1;
            int bossId = -1;
            BossEnemy boss = null;
            if (selectedBossIndex > -1)
            {
                bossId = int.Parse(bossLv.SelectedItems[0].SubItems[0].Text);
                boss = presenter.BossPresenter.GetBoss(bossId);
            }

            // draw image
            if (bDrawBossImg)
            {
                if (boss == null || string.IsNullOrEmpty(boss.TextureName))
                    return;

                e.Graphics.DrawImage(Image.FromFile(boss.TextureName), Point.Empty);
            }
            else
            {
                if (bossSpritesLbx.SelectedIndex >= 0)
                    e.Graphics.DrawImage(Image.FromFile(bossSpritesLbx.Items[bossSpritesLbx.SelectedIndex].ToString()), Point.Empty);
            }

            // draw rectangles
            if (!bCanBossDrawRect)
            {
                if (bossId > 0)
                {
                    if (boss != null)
                    {
                        curSourceRect = boss.SourceRect;

                        e.Graphics.DrawRectangles(redPen, (from r in boss.CollisionRectangles
                                                           select new Rectangle(r.X, r.Y, r.Width, r.Height)).ToArray());
                    }
                }
            }
            else
            {
                e.Graphics.DrawRectangle(redPen, curColRect);
            }

            e.Graphics.DrawRectangle(bluePen, curSourceRect);
        }
        #endregion


        #region FighterPods
        #endregion


        #region Bullets
        #endregion


        #region Weapons
        #endregion


        #region Editor
        private void saveToolStripMenuItem_Click(object sender, EventArgs e)
        {
            try
            {
                if(string.IsNullOrEmpty(curFilename))
                {
                    using (FileDialog dlg = new SaveFileDialog())
                    {
                        if (DialogResult.OK != dlg.ShowDialog())
                            return;

                        curFilename = dlg.FileName;
                        Settings.Default.LastSaveFile = curFilename;
                        Settings.Default.Save();
                    }
                }
                presenter.SaveGameFile(curFilename);
            }
            catch
            {
                MessageBox.Show(Resources.gameFileSaveError, Resources.editorErrorTitle);
            }
        }

        private void saveAsToolStripMenuItem_Click(object sender, EventArgs e)
        {
            try
            {
                using (FileDialog dlg = new SaveFileDialog())
                {
                    if (DialogResult.OK != dlg.ShowDialog())
                        return;

                    curFilename = dlg.FileName;
                    Settings.Default.LastSaveFile = curFilename;
                    Settings.Default.Save();

                    presenter.SaveGameFile(curFilename);
                }
            }
            catch
            {
                MessageBox.Show(Resources.gameFileSaveError, Resources.editorErrorTitle);
            }
        }

        private void openToolStripMenuItem_Click(object sender, EventArgs e)
        {
            using (FileDialog dlg = new OpenFileDialog())
            {
                if (DialogResult.OK != dlg.ShowDialog())
                    return;

                curFilename = dlg.FileName;

                LoadGameData(presenter.LoadApplicationData(curFilename));
            }
        }

        private void newToolStripMenuItem_Click(object sender, EventArgs e)
        {
            LoadGameData(presenter.LoadApplicationData(null));
        }
        #endregion


        #region Paint Events
        private void menuContainer_Panel1_Paint(object sender, PaintEventArgs e)
        {
            e.Graphics.DrawRectangle(new Pen(Color.Blue, 3), viewport);

            if (curImage != null)
                e.Graphics.DrawImage(curImage, viewport);

            if (menusLbx.SelectedIndex < 0) return;

            //GameMenu menu = presenter.MenuPresenter.GetMenu(menusLbx.SelectedIndex);
            //for (int i = 0; i < menu.MenuOptions.Count; ++i)
            //{
            //    MenuOption option = menu.MenuOptions[i];
            //    Font font = new Font(menu.SpriteFont.FontName, menu.SpriteFont.Size, menu.SpriteFont.FontStyle);
            //    Brush brush = new SolidBrush(Color.FromName(menu.Color));
            //    float x = viewport.Left + (viewport.Width * 0.5f);
            //    float y = viewport.Top + (viewport.Height * 0.5f) + (i * 25);
            //    e.Graphics.DrawString(option.Title, font, brush, x, y);
            //}
        }

        private void levelsCanvas_Paint(object sender, PaintEventArgs e)
        {
            string background = "";

            //if (levelsLv.SelectedIndices.Count > 0)
            //{
            //    int id = int.Parse(levelsLv.SelectedItems[0].SubItems[0].Text);
            //    background = presenter.ProtagonistPresenter.GetLevel(-1, id).Background;
            //}
            //else if (levelBkgLbx.SelectedIndex > 0)
            //{
            //    background = presenter.ProtagonistPresenter.GetLevel(levelBkgLbx.SelectedIndex).Background;
            //}

            if (!string.IsNullOrEmpty(background))
                e.Graphics.DrawImage(Image.FromFile(background), viewport);
        }
        #endregion


        #region Selected Index Changed Events
        /// <summary>
        /// Handles the SelectedIndexChanged event of the bkgsLbx control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        private void bkgsLbx_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (bkgsLbx.SelectedIndex < 0) return;

            curImage = Image.FromFile((string)bkgsLbx.Items[bkgsLbx.SelectedIndex]);
            menuContainer.Panel1.Invalidate();
        }

        private void newMenuToolStripMenuItem_Click(object sender, EventArgs e)
        {
            GameMenu menu = new GameMenu();
            menusLbx.Items.Add(menu.Title);
            //presenter.ProtagonistPresenter.AddMenu(menu);

            menusLbx.Invalidate();
        }

        private void menusLbx_SelectedIndexChanged(object sender, EventArgs e)
        {
            menuContainer.Panel1.Invalidate();
        }

        private void levelsLv_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (levelsLv.SelectedIndices.Count == 0)
                return;

            levelsCanvas.Invalidate();
        }
        #endregion


        #region Click Events
        private void addLevelMenuItem_Click(object sender, EventArgs e)
        {
            //IList<Enemy> enemies = presenter.ProtagonistPresenter.GetObjects<Enemy>();

            //using (LevelEditForm form = new LevelEditForm(new GameLevel { ID = presenter.ProtagonistPresenter.GetLevelCount() + 1 }, enemies))
            //{
            //    if (DialogResult.OK != form.ShowDialog())
            //        return;

            //    presenter.ProtagonistPresenter.AddLevel(form.GameLevel);

            //    levelsLv.Items.Add(new ListViewItem(new[]
            //                                        {
            //                                            form.GameLevel.ID.ToString(),
            //                                            form.GameLevel.StartTime.ToString(),
            //                                            form.GameLevel.LevelWaves.Count.ToString()
            //                                        }));
            //}
        }

        private void editLevelMenuItem_Click(object sender, EventArgs e)
        {
            if (levelsLv.SelectedIndices.Count == 0)
                return;

            ShowLevelEditForm();
        }

        private void removeLevelMenuItem_Click(object sender, EventArgs e)
        {
            int index = levelsLv.SelectedIndices[0];
            if (index < 0)
                return;

            if (DialogResult.Yes != MessageBox.Show(Resources.LevelRemovalPrompt, Resources.GameEditorTitle, MessageBoxButtons.YesNo))
                return;

            levelsLv.Items.RemoveAt(index);

            //presenter.ProtagonistPresenter.RemoveLevel(index);
        }

        private void setLevelBkgMenuItem_Click(object sender, EventArgs e)
        {
            if (levelBkgLbx.SelectedIndex < 0 || levelsLv.SelectedIndices.Count == 0)
                return;

            //GameLevel level = presenter.ProtagonistPresenter.GetLevel(levelBkgLbx.SelectedIndex);
            //level.Background = levelBkgLbx.Items[levelBkgLbx.SelectedIndex].ToString();

            levelsCanvas.Invalidate();
        }

        private void removeColRectBtn_Click(object sender, EventArgs e)
        {
            if (curLv.SelectedIndices.Count == 0 ||
                protColRectsLv.SelectedIndices.Count == 0)
            {
                return;
            }

            int id = int.Parse(curLv.Items[curLv.SelectedIndices[0]].SubItems[0].Text);

            //presenter.ProtagonistPresenter.RemoveCollisionRectangle(id, protColRectsLv.SelectedIndices[0]);
        }

        private void levelsLv_MouseDoubleClick(object sender, MouseEventArgs e)
        {
            ShowLevelEditForm();
        }
        #endregion


        #region Utility Functions
        private void InitStartData(EditorStartData startData)
        {
            bkgsLbx.Items.AddRange(startData.MenuBackgrounds);
            fontsLbx.Items.AddRange(startData.FontFiles);
            soundsLbx.Items.AddRange(startData.SoundFiles);
            levelBkgLbx.Items.AddRange(startData.LevelBackgrounds);
        }

        private void LoadGameData(EditorStartData editorStartData)
        {
            GameData gameData = editorStartData.GameData;

            if (!string.IsNullOrEmpty(Settings.Default.LastSaveFile))
                curFilename = Settings.Default.LastSaveFile;

            // load protagonists
            LoadProtagonistUI(gameData.Protagonists, gameData.Weapons, editorStartData.ProtagonistSprites);

            // load enemies
            LoadEnemyUI(gameData.Enemies, gameData.Weapons, editorStartData.EnemySprites);

            // TODO: load mini bosses
            LoadMinibossUI(gameData.MiniBosses, gameData.Weapons, editorStartData.MinibossSprites);

            // TODO: load bosses
            LoadBossUI(gameData.Bosses, gameData.Weapons, editorStartData.BossSprites);

            // TODO: load fighter pods
            LoadFighterPodUI(gameData.FighterPods, gameData.Weapons, editorStartData.FighterPodSprites);

            // TODO: load bullets
            LoadBulletUI(gameData.Bullets, gameData.Effects, editorStartData.BulletSprites);

            // TODO: load weapons
            LoadWeaponUI(gameData.Weapons, gameData.Bullets);

            // TODO: load Bullet Effects
            //LoadBulletEffectUI(gameData.MiniBosses, gameData.Weapons, editorStartData.MinibossSprites);

            // TODO: load levels

            // TODO: load menus

            // TODO: load shaders

            // TODO: load animations
        }

        private void LoadWeaponUI(IEnumerable<WeaponBase> weapons, IEnumerable<BulletBase> bullets)
        {
            foreach (var weapon in weapons)
            {
                weaponsLv.Items.Add(new ListViewItem(new[]
                                                              {
                                                                  weapon.ID.ToString(),
                                                                  weapon.ShootInterval.ToString(),
                                                                  weapon.BulletCount.ToString(),
                                                                  weapon.RequiredSlots.ToString(),
                                                              }));
            }

            foreach (var bullet in bullets)
            {
                weaponBulletsLv.Items.Add(new ListViewItem(new[]
                                                              {
                                                                  bullet.ID.ToString(),
                                                                  bullet.Power.ToString(),
                                                                  bullet.Speed.ToString(),
                                                                  bullet.EnergyPerHit.ToString(),
                                                              }));
            }
        }

        private void LoadBulletUI(IEnumerable<BulletBase> bullets, IEnumerable<EffectBase> effects, string[] bulletSprites)
        {
            foreach (var bullet in bullets)
            {
                bulletsLv.Items.Add(new ListViewItem(new[]
                                                              {
                                                                  bullet.ID.ToString(),
                                                                  bullet.Power.ToString(),
                                                                  bullet.Speed.ToString(),
                                                                  bullet.EnergyPerHit.ToString(),
                                                              }));
            }

            //foreach (var effect in effects)
            //{
            //    bulletEffectsLv.Items.Add(new ListViewItem(new[]
            //                                                  {
            //                                                      effect.ID.ToString(),
            //                                                      effect.RequiredSlots.ToString(),
            //                                                      effect.BulletCount.ToString(),
            //                                                      effect.ShootInterval.ToString()
            //                                                  }));
            //}

            bulletSpritesLbx.Items.AddRange(bulletSprites);
        }

        private void LoadFighterPodUI(IEnumerable<FighterPod> fighterPods, IEnumerable<WeaponBase> weapons, string[] fighterPodSprites)
        {
            foreach (var fighterPod in fighterPods)
            {
                fighterPodsLv.Items.Add(new ListViewItem(new[]
                                                              {
                                                                  fighterPod.ID.ToString(),
                                                                  fighterPod.Power.ToString(),
                                                                  fighterPod.Speed.ToString(),
                                                                  fighterPod.WeaponSlots.ToString(),
                                                              }));
            }

            foreach (var weapon in weapons)
            {
                fighterPodWeaponsLv.Items.Add(new ListViewItem(new[]
                                                              {
                                                                  weapon.ID.ToString(),
                                                                  weapon.RequiredSlots.ToString(),
                                                                  weapon.BulletCount.ToString(),
                                                                  weapon.ShootInterval.ToString()
                                                              }));
            }

            fighterPodsSpritesLbx.Items.AddRange(fighterPodSprites);
        }

        private void LoadBossUI(IEnumerable<BossEnemy> bosses, IEnumerable<WeaponBase> weapons, string[] bossSprites)
        {
            foreach (var boss in bosses)
            {
                bossLv.Items.Add(new ListViewItem(new[]
                                                              {
                                                                  boss.ID.ToString(),
                                                                  boss.Power.ToString(),
                                                                  boss.Speed.ToString(),
                                                                  boss.WeaponSlots.ToString(),
                                                              }));
            }

            foreach (var weapon in weapons)
            {
                bossWeaponsLv.Items.Add(new ListViewItem(new[]
                                                              {
                                                                  weapon.ID.ToString(),
                                                                  weapon.RequiredSlots.ToString(),
                                                                  weapon.BulletCount.ToString(),
                                                                  weapon.ShootInterval.ToString()
                                                              }));
            }

            bossSpritesLbx.Items.AddRange(bossSprites);
        }

        private void LoadMinibossUI(IEnumerable<MiniBossEnemy> miniBosses, IEnumerable<WeaponBase> weapons, string[] minibossSprites)
        {
            foreach (var miniboss in miniBosses)
            {
                miniBossLv.Items.Add(new ListViewItem(new[]
                                                              {
                                                                  miniboss.ID.ToString(),
                                                                  miniboss.Power.ToString(),
                                                                  miniboss.Speed.ToString(),
                                                                  miniboss.WeaponSlots.ToString(),
                                                              }));
            }

            foreach (var weapon in weapons)
            {
                miniBossWeaponsLv.Items.Add(new ListViewItem(new[]
                                                              {
                                                                  weapon.ID.ToString(),
                                                                  weapon.RequiredSlots.ToString(),
                                                                  weapon.BulletCount.ToString(),
                                                                  weapon.ShootInterval.ToString()
                                                              }));
            }

            miniBossSpritesLbx.Items.AddRange(minibossSprites);
        }

        private void LoadProtagonistUI(IEnumerable<Protagonist> protagonists, IEnumerable<WeaponBase> weapons, string[] protagonistSprites)
        {
            foreach (var protagonist in protagonists)
            {
                protagonistsLv.Items.Add(new ListViewItem(new[]
                                                              {
                                                                  protagonist.ID.ToString(),
                                                                  protagonist.Hp.ToString(),
                                                                  protagonist.Power.ToString(),
                                                                  protagonist.Speed.ToString(),
                                                                  protagonist.WeaponSlots.ToString(),
                                                              }));
            }

            foreach (var weapon in weapons)
            {
                protWeaponLv.Items.Add(new ListViewItem(new[]
                                                              {
                                                                  weapon.ID.ToString(),
                                                                  weapon.RequiredSlots.ToString(),
                                                                  weapon.BulletCount.ToString(),
                                                                  weapon.ShootInterval.ToString()
                                                              }));
            }

            protSpritesLbx.Items.AddRange(protagonistSprites);
        }

        private void LoadEnemyUI(IEnumerable<NormalEnemy> enemies, IEnumerable<WeaponBase> weapons, string[] enemySprites)
        {
            foreach (var enemy in enemies)
            {
                enemiesLv.Items.Add(new ListViewItem(new[]
                                                              {
                                                                  enemy.ID.ToString(),
                                                                  enemy.Hp.ToString(),
                                                                  enemy.Power.ToString(),
                                                                  enemy.Speed.ToString(),
                                                                  enemy.WeaponSlots.ToString(),
                                                              }));
            }

            foreach (var weapon in weapons)
            {
                protWeaponLv.Items.Add(new ListViewItem(new[]
                                                              {
                                                                  weapon.ID.ToString(),
                                                                  weapon.RequiredSlots.ToString(),
                                                                  weapon.BulletCount.ToString(),
                                                                  weapon.ShootInterval.ToString()
                                                              }));
            }

            protSpritesLbx.Items.AddRange(enemySprites);
        }

        private void ShowLevelEditForm()
        {
            //IList<Enemy> enemies = presenter.ProtagonistPresenter.GetObjects<Enemy>();

            // int lvIndex = levelsLv.SelectedIndices[0];

            //GameLevel level = presenter.ProtagonistPresenter.GetLevel(lvIndex);

            //using (LevelEditForm form = new LevelEditForm(level, enemies))
            //{
            //    if (DialogResult.OK != form.ShowDialog())
            //        return;

            //    //presenter.ProtagonistPresenter.SetLevel(lvIndex, form.GameLevel);

            //    levelsLv.Items[lvIndex].SubItems[0].Text = form.GameLevel.ID.ToString();
            //    levelsLv.Items[lvIndex].SubItems[1].Text = form.GameLevel.StartTime.ToString();
            //    levelsLv.Items[lvIndex].SubItems[2].Text = form.GameLevel.LevelWaves.Count.ToString();
            //}
        }
        #endregion

        private void bossWeaponsLv_MouseClick(object sender, MouseEventArgs e)
        {

        }
    }
}